/*
 * CPU.c
 *
 *  Created on: Nov 29, 2012
 *      Author: theboss
 */

#include "cpu.h"
#include <stdlib.h>

Cpu *new_cpu(Memory *memory, RegisterSet *reg_file)	//PLEASE NOTE DUE TO CIRCULAR REFERENCING YOU HAVE TO MANUALLY CHANGE
{													//CPU->alu to the alu, because Alu must be constructed with a reference to cpu.
	Cpu *cpu = (Cpu *)malloc(sizeof(Cpu));

	cpu->memory = memory;
	cpu->registerset = reg_file;
	cpu->alu = new_alu(cpu);
	cpu->controller = new_controller(cpu, cpu->alu, memory, reg_file);
	return cpu;
}

Controller *cpu_get_controller(Cpu *cpu)
{
	return cpu->controller;
}

void cpu_perform_instruction(Cpu *cpu)
{
	if (cpu->stop_bit == FALSE)
		controller_step(cpu->controller);
}

void cpu_halt(Cpu *cpu)
{
	cpu->stop_bit = TRUE;
}

Register cpu_get_pc(Cpu *cpu)
{
	return cpu->PC;
}

void cpu_set_pc(Cpu *cpu, Register value)
{
	cpu->PC = value;
}

Register cpu_get_ir(Cpu *cpu)
{
	return cpu->IR;
}

void cpu_set_ir(Cpu *cpu, Register value)
{
	cpu->IR = value;
}

Register cpu_get_state(Cpu *cpu)
{
	return cpu->state;
}

void cpu_set_state(Cpu *cpu, Register value)
{
	cpu->state = value;
}

Register sign_extend(Register value, Register bit_mask)
{
	Register value_mask = bit_mask >> 1;
	Register sign_bit_mask = bit_mask & ~value_mask;
	int sign_value = value & sign_bit_mask;

	if (sign_value)
		return (~0 & ~value_mask) | (value & value_mask);
	else
		return value & value_mask;
}

void free_cpu(Cpu *cpu)
{
	free(cpu);
}
